package main

import (
	"fmt"
	"gintest/chatroom/server/model"
	"net"
	"time"
)

//func readPkg(conn net.Conn) (mes message.Message, err error) {
//	buf := make([]byte, 8096)
//	fmt.Println("读取客户端发送的数据。。。")
//	//为什么这里读不到会阻塞
//	//conn.Read在conn没有被关闭的情况下，才会阻塞
//	//如果客户端关闭了conn，则，就不会阻塞
//	n, err := conn.Read(buf[:4])
//	if n != 4 || err != nil {
//		//fmt.Println("conn.Read(buf[:4]) err = ", err)
//		//err = errors.New("read pkg header error")
//		return
//	}
//	//fmt.Println("读到的长度为=", buf[:4])
//	//根据buf[:4]转成一个uint32类型
//	var pkgLen uint32
//	pkgLen = binary.BigEndian.Uint32(buf[:4])
//	//根据pkgLen读取消息内容
//	//从conn套接字里面读取[0：pkgLen]个数据，再放到buf里面
//	n, err = conn.Read(buf[:pkgLen])
//	if n != int(pkgLen) || err != nil {
//		//fmt.Println("conn.Read(buf[:pkgLen]) err = ", err)
//		//err = errors.New("read pkg body error")
//		return
//	}
//	//把pkgLen反序列化成 -> message.Message
//	//一定要加上&，技术就是一层窗户纸
//	err = json.Unmarshal(buf[:pkgLen], &mes)
//	if err != nil {
//		fmt.Println("json.Unmarshal(buf[:pkgLen],&mes) err = ", err)
//		return
//	}
//	return
//}

//func writePkg(conn net.Conn, data []byte) (err error) {
//	//先发送一个长度给对方
//	var pkgLen uint32
//	pkgLen = uint32(len(data))
//	var buf [4]byte
//	binary.BigEndian.PutUint32(buf[0:4], pkgLen)
//	//发送长度
//	n, err := conn.Write(buf[0:4])
//	if n != 4 || err != nil {
//		fmt.Println("conn.Write(bytes) fail err = ", err)
//		return
//	}
//
//	//发送data数据本身
//	n, err = conn.Write(data)
//	if n != int(pkgLen) || err != nil {
//		fmt.Println("conn.Write(data) fail err = ", err)
//		return
//	}
//	return
//}

////编写一个函数serverProcessLogin函数，专门处理登录请求
//func serverProcessLogin(conn net.Conn, mes *message.Message) (err error) {
//	//核心代码。。。
//	//1.先从mes中取出mes.Data， 并直接反序列化成loginMes
//	var loginMes message.LoginMes
//	err = json.Unmarshal([]byte(mes.Data), &loginMes)
//	if err != nil {
//		fmt.Println("000json.Unmarshal([]byte(mes.Data), loginMes) err = ", err)
//		return
//	}
//
//	//1先声明一个resMes
//	var resMes message.Message
//	resMes.Type = message.LoginResMesType
//
//	//2再声明一个LoginResMes，并赋值
//	var loginResMes message.LoginResMes
//
//	//判断，如果id=100，密码=123456，合法，否则不合法
//	if loginMes.UserId == 100 && loginMes.UserPwd == "123456" {
//		//合法
//		loginResMes.Code = 200
//
//	} else {
//		//不合法
//		loginResMes.Code = 500
//		loginResMes.Error = "该用户不存在。。。先去注册后使用"
//	}
//
//	//3将loginResMes序列化
//	data, err := json.Marshal(loginResMes)
//	if err != nil {
//		fmt.Println("json.Marshal(loginResMes) err = ", err)
//		return
//	}
//
//	//4将data赋值给resMes
//	resMes.Data = string(data)
//
//	//5.对resMes进行序列化，准备发送
//	data, err = json.Marshal(resMes)
//	if err != nil {
//		fmt.Println("json.Marshal(resMes) err = ", err)
//		return
//	}
//	//6.发送data，将其封装到writePkg钟
//	err = writePkg(conn, data)
//	return
//}

////编写一个ServerProcessMes 函数
////功能： 根据客户端发送消息种类不同，决定调用哪个函数来处理，用switch
//func serverProcessMes(conn net.Conn, mes *message.Message) (err error) {
//	switch mes.Type {
//	case message.LoginMesType:
//		//处理账号登录
//		err = serverProcessLogin(conn, mes)
//	case message.RegisterMesTpe:
//		//处理注册
//	default:
//		fmt.Println("消息类型不存在，无法处理。。。")
//	}
//	return
//}

//处理和客户端的通讯
//这个套接字是引用类型，所以不用加*
func process(conn net.Conn) {
	//记得延时关闭coon
	defer conn.Close()

	////循环读客户端发送的信息
	//for {
	//
	//	//这里我们将读取数据包，直接封装成一个函数readPkg()，返回Message, err
	//	mes, err := readPkg(conn)
	//	if err != nil {
	//		if err == io.EOF {
	//			fmt.Println("客户端退出，服务端也退出")
	//			return
	//		} else {
	//			fmt.Println(" readPkg(conn) err", err)
	//			return
	//		}
	//	}
	//	fmt.Println("mes = ", mes)
	//
	//	err = serverProcessMes(conn, &mes)
	//	if err != nil {
	//		return
	//	}
	//
	//}

	//这里调用总控
	processor := &Processor{
		Conn: conn,
	}
	err := processor.process2()
	if err != nil {
		fmt.Println("客户端和服务器通讯协程错误=err", err)
		return
	}

}

//这里我们编写一个函数，完成对userdao的初始化任务
func initUserDao() {
	//这里的pool本身就是全局变量
	//这里需要注意初始化顺序问题，先initPool，再initUserDao
	model.MyUserDao = model.NewUserDao(pool)

}

func main() {
	//当服务器启动时，我们就去初始化redis连接池
	initPool("localhost:6379", 16, 0, 300*time.Second)
	initUserDao()

	//提示信息
	fmt.Println("服务器[新的结构]在8889端口监听")
	listen, err := net.Listen("tcp", "0.0.0.0:8889")
	defer listen.Close()
	if err != nil {
		fmt.Println("不监听了，算了，net.Listen err = ", err)
		return
	}
	//一旦监听成功，就等待客户端连接服务器
	for {
		fmt.Println("等待客户端来连接服务器。。。")
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("listen.Accept err = ", err)
		}

		//一旦连接成功，则启动一个协程和客户端保持通讯
		go process(conn)
	}

}
